`timescale 1ns / 1ps
/************************************************************\
 **  Copyright (c) 2022-2023 Gonsin, Inc.
 **  All Right Reserved.
 **  Author: http://www.anlogic.com/
 **  Description: temac_locallink
 **  Rev 1.0
\************************************************************/

module temac_locallink #(
parameter P_ADD_FILT_EN = 1'b1,   // 如果为true，则内核支持地址过滤。
parameter P_ADD_FILT_LIST = 16,		// 内核支持的地址表可配置地址个数
parameter P_HALF_DUPLEX = 1'b1,		// 如果为true，则内核半双工和全双工模式，否则仅支持全双工模式。
parameter P_HOST_EN = 1'b1,		    // 如果为true，则内核仅支持AXI接口管理配置，否则内核仅支持矢量总线配置。
parameter P_SPEED_1000 = 1'b0,		// 如果为true，则内核仅支持1000 Mbps速度。
parameter P_SPEED_10_100 = 1'b0,	// 如果为true，则内核仅支持10/100 Mbps速度。
parameter P_TRI_SPEED = 1'b1		  // 如果为true，则内核支持3速
)
(  
// 异步复位
//---------------------------------------
input reset_i,

//全局发送时钟
//--------------------------
input gtx_clk_i,

// 客户端接收接口
//---------------------------------------
output rx_clk_o,
output rx_clkEn_o,
output [26:0] rx27b_statusVector_o,
output rx_statusVld_o,

// 客户端接收（FIFO侧）接口
//----------------------------------------
input rx_LLclock_i,
input rx_LLreset_i,
output [7:0] rx8b_LLdata_o,
output rx_LLsof_outN_o,
output rx_LLeof_outN_o,
output rx_LLsrcRdy_outN_o,
input rx_LLdstRdy_inN_i,

// 客户端发送器接口
//------------------------------------------
output tx_clk_o,
output tx_clkEn_o,
output tx_rdy_o,   // For test
input tx_stop_i,
input [7:0] tx8b_ifgVal_i,
output [28:0] tx29b_statusVector_o,
output tx_statusVld_o,

// 客户端发送（FIFO侧）接口
//-------------------------------------------
input tx_LLclock_i,
input tx_LLreset_i,
input [7:0] tx8b_LLdata_i,
input tx_LLsof_inN_i,
input tx_LLeof_inN_i,
input tx_LLsrcRdy_inN_i,
output tx_LLdstRdy_outN_o,

// 流控接口
//--------------------------------
input pause_req_i,
input [15:0] pause16b_val_i,
input [47:0] pause48b_sourceAddr_i,

// 初始默认单播地址值
//--------------------------------
input [47:0] unicast48b_address_i,

// AXI主机管理接口
//-----------------------------------	  
//AXI总线
input sAXI_aclk_i,
input [7:0] sAXI8b_awaddr_i,
input sAXI_awvalid_i,
output sAXI_awready_o,
input [31:0] sAXI32b_wdata_i,   
input sAXI_wvalid_i,
output sAXI_wready_o,
output [1:0] sAXI2b_bresp_o,
output sAXI_bvalid_o,
input sAXI_bready_i,
input [7:0] sAXI8b_araddr_i,
input sAXI_arvalid_i,
output sAXI_arready_o,
output [31:0] sAXI32b_rdata_o,
output [1:0] sAXI2b_rresp_o,
output sAXI_rvalid_o,
input sAXI_rready_i,

// 向量配置总线
//-----------------------------
input [19:0] mac20b_cfgVector_i,

// RGMII 接口
//----------------------------------
output [3:0] rgmii4b_txd_o,
output rgmii_txCtl_o,
output rgmii_txc_o,
input [3:0] rgmii4b_rxd_i,
input rgmii_rxCtl_i,
input rgmii_rxc_i,

// RGMII 状态寄存器
//--------------------------------
output inband_linkStatus_o,
output [1:0] inband2b_clockSpeed_o,
output inband_duplexStatus_o,

// MDIO 接口
//------------------------------
input mdio_i,
output mdio_o,
output mdio_oen_o,
output mdio_clk_o
);

//----------------------------------------------------------------------------
// 模块内部信号
//----------------------------------------------------------------------------

//rx域 接收时钟 及 复位信号
//-----------------------
wire rx_clkInt_w;    
wire rx_clkEn_w; 

wire rx_resetInt_w;  
reg rx_pre_reset;  
reg rx_reset;      

//tx域 发送时钟 及 复位信号
//-----------------------
wire tx_clkInt_w;    
wire tx_clkEn_w; 

wire tx_resetInt_w;  
reg tx_pre_reset;  
reg tx_reset;      

// 客户端接收接口
//-----------------------
wire [7:0] rxdata8b_w;
wire rxdata_valid_w;
wire rx_correctFrame_w;
wire rx_errorFrame_w;

// 客户端发送接口
//-----------------------
wire [7:0] txdata8b_w;
wire txdata_en_w;

wire tx_collision_w;
wire tx_retransmit_w;

//----------------------------------------------------------------------------
// 将 时钟信号/时钟使能信号 输出
//----------------------------------------------------------------------------
assign rx_clk_o = rx_clkInt_w;
assign rx_clkEn_o = rx_clkEn_w;
assign tx_clk_o = tx_clkInt_w;
assign tx_clkEn_o = tx_clkEn_w;

//---------------------------------------------------------------------------
// 例化 复位同步
//---------------------------------------------------------------------------

// 在Tx时钟域中生成同步复位信号
reset_sync tx_reset_gen (
.clk_i(tx_clkInt_w),
.enable_i(1'b1),
.reset_i(reset_i),
.reset_o(tx_resetInt_w)
);

// 在Tx时钟域中生成 完全同步复位
always@(posedge tx_clkInt_w) begin
  if (tx_resetInt_w) begin
    tx_pre_reset <= 1;
    tx_reset <= 1;
  end
  else begin
    tx_pre_reset <= 0;
    tx_reset <= tx_pre_reset;
  end
end 

//-----------------------------------------------------------------------
// 在rx时钟域中生成 同步复位信号
reset_sync rx_reset_gen (
.clk_i(rx_clkInt_w),
.enable_i(1'b1),
.reset_i(reset_i),
.reset_o(rx_resetInt_w)
);

// 在rx时钟域中生成 完全同步复位
always@(posedge rx_clkInt_w) begin
  if (rx_resetInt_w) begin
    rx_pre_reset <= 1;
    rx_reset <= 1;
  end
  else begin
    rx_pre_reset <= 0;
     rx_reset <= rx_pre_reset;
  end
end 

//----------------------------------------------------------------------------
// 例化客户端FIFO
//----------------------------------------------------------------------------
client_FIFO #(
.FULL_DUPLEX_ONLY(0)
) client_FIFO_u (
// MAC TX 接口
.tx_reset_i(tx_reset),
.tx_clk_i(tx_clkInt_w),      
.tx_clk_en_i(tx_clkEn_w),
.txdata8b_o(txdata8b_w),
.txdata_en_o(txdata_en_w),
.tx_rdy_i(tx_rdy_o),
.tx_collision_i(tx_collision_w),
.tx_retransmit_i(tx_retransmit_w),

// 客户端发送（FIFO侧）接口
.tx_LLclock_i(tx_LLclock_i),
.tx_LLreset_i(tx_LLreset_i),
.tx8b_LLdata_i(tx8b_LLdata_i),
.tx_LLsof_inN_i(tx_LLsof_inN_i),
.tx_LLeof_inN_i(tx_LLeof_inN_i),
.tx_LLsrcRdy_inN_i(tx_LLsrcRdy_inN_i),
.tx_LLdstRdy_outN_o(tx_LLdstRdy_outN_o),
.tx4b_fifoStatus_o(),
.tx_overflow_o(),

// MAC RX 接口
.rx_reset_i(rx_reset),
.rx_clk_i(rx_clkInt_w),     
.rx_clkEn_i(rx_clkEn_w),
.rxdata8b_i(rxdata8b_w),
.rxdata_valid_i(rxdata_valid_w),
.rx_correctFrame_i(rx_correctFrame_w),
.rx_errorFrame_i(rx_errorFrame_w),
.rx_overflow_o(),

// 客户端接收（FIFO侧）接口
.rx_LLclock_i(rx_LLclock_i),
.rx_LLreset_i(rx_LLreset_i),
.rx8b_LLdata_o(rx8b_LLdata_o),
.rx_LLsof_outN_o(rx_LLsof_outN_o),
.rx_LLeof_outN_o(rx_LLeof_outN_o),
.rx_LLsrcRdy_outN_o(rx_LLsrcRdy_outN_o),
.rx_LLdstRdy_inN_i(rx_LLdstRdy_inN_i),
.rx4b_fifoStatus_o()
);

//----------------------------------------------------------------------------
// 例化 TEMAC Block 模块
//----------------------------------------------------------------------------
temac_block #(
.P_ADD_FILT_EN(P_ADD_FILT_EN), 
.P_ADD_FILT_LIST(P_ADD_FILT_LIST),   
.P_HALF_DUPLEX(P_HALF_DUPLEX), 
.P_HOST_EN(P_HOST_EN), 
.P_SPEED_1000(P_SPEED_1000), 
.P_SPEED_10_100(P_SPEED_10_100), 
.P_TRI_SPEED(P_TRI_SPEED)
) temac_block_u (
// 异步复位
.reset_i(reset_i),

//全局发送时钟
.gtx_clk_i(gtx_clk_i),

// 客户端接收接口
.rx_clk_o(rx_clkInt_w),
.rx_clkEn_o(rx_clkEn_w),
.rxdata8b_o(rxdata8b_w),
.rxdata_valid_o(rxdata_valid_w),
.rx_correctFrame_o(rx_correctFrame_w),
.rx_errorFrame_o(rx_errorFrame_w),
.rx27b_statusVector_o(rx27b_statusVector_o),
.rx_statusVld_o(rx_statusVld_o),

// 客户发送器接口
.tx_clk_o(tx_clkInt_w),
.tx_clken_o(tx_clkEn_w),
.txdata8b_i(txdata8b_w),
.txdata_en_i(txdata_en_w),
.tx_rdy_o(tx_rdy_o),
.tx_stop_i(tx_stop_i),
.tx_collision_o(tx_collision_w),
.tx_retransmit_o(tx_retransmit_w),
.tx8b_ifgVal_i(tx8b_ifgVal_i),
.tx29b_statusVector_o(tx29b_statusVector_o),
.tx_statusVld_o(tx_statusVld_o),

//流控接口
.pause_req_i(pause_req_i),
.pause16b_val_i(pause16b_val_i),
.pause48b_sourceAddr_i(pause48b_sourceAddr_i),

//初始默认单播地址值
.unicast48b_address_i(unicast48b_address_i),

// AXI主机管理接口
.sAXI_aclk_i(sAXI_aclk_i), 
.sAXI8b_awaddr_i(sAXI8b_awaddr_i),    //input  wire [7:0]     
.sAXI_awvalid_i(sAXI_awvalid_i),      //input  wire             
.sAXI_awready_o(sAXI_awready_o),      //output wire             
.sAXI32b_wdata_i(sAXI32b_wdata_i),    //input  wire [31:0]     
.sAXI_wvalid_i(sAXI_wvalid_i),        //input  wire             
.sAXI_wready_o(sAXI_wready_o),        //output wire             
.sAXI2b_bresp_o(sAXI2b_bresp_o),      //output wire [1:0]     
.sAXI_bvalid_o(sAXI_bvalid_o),        //output wire             
.sAXI_bready_i(sAXI_bready_i),        //input  wire             
.sAXI8b_araddr_i(sAXI8b_araddr_i),    //input  wire [7:0]     
.sAXI_arvalid_i(sAXI_arvalid_i),      //input  wire             
.sAXI_arready_o(sAXI_arready_o),      //output wire             
.sAXI32b_rdata_o(sAXI32b_rdata_o),    //output wire [31: 0]     
.sAXI2b_rresp_o(sAXI2b_rresp_o),      //output wire [1 : 0]     
.sAXI_rvalid_o(sAXI_rvalid_o),        //output wire             
.sAXI_rready_i(sAXI_rready_i),        //input  wire

// 向量配置总线
.mac20b_cfgVector_i(mac20b_cfgVector_i),

// RGMII接口
.rgmii4b_txd_o(rgmii4b_txd_o),
.rgmii_txCtl_o(rgmii_txCtl_o),
.rgmii_txc_o(rgmii_txc_o),
.rgmii4b_rxd_i(rgmii4b_rxd_i),
.rgmii_rxCtl_i(rgmii_rxCtl_i),
.rgmii_rxc_i(rgmii_rxc_i),
.inband_linkStatus_o(inband_linkStatus_o),
.inband2b_clockSpeed_o(inband2b_clockSpeed_o),
.inband_duplexStatus_o(inband_duplexStatus_o),

// MDIO 接口
.mdio_i(mdio_i),
.mdio_o(mdio_o),
.mdio_oen_o(mdio_oen_o),
.mdio_clk_o(mdio_clk_o)
);

endmodule